package com.by.toolkit.utils;

import cn.hutool.core.net.Ipv4Util;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.regex.Pattern;

/**
 * ip工具类
 *
 * @author YanBingHao
 * @since 2024/1/2
 */
public class IpUtil {

    private static final Pattern IPV4_PATTERN = Pattern
            .compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");

    public static boolean isIpV4(final String ip) {
        if (StringUtils.isBlank(ip)) {
            return false;
        }

        return IPV4_PATTERN.matcher(ip).matches();
    }

    private static final String[] IP_HEADER_CANDIDATES = {"X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED", "HTTP_X_CLUSTER_CLIENT_IP", "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR", "HTTP_FORWARDED", "HTTP_VIA", "REMOTE_ADDR"};

    /**
     * 注意: 不要使用localhost作为请求url里面的host,例如http://localhost:8080/login. 这样做remote
     * ip会返回空.
     *
     * @param request
     * @return
     */
    public static String getRemoteIp(HttpServletRequest request) {
        return getRemoteIpV4(request);
    }

    public static String getRemoteIpV4(HttpServletRequest request) {
        String remoteIp = null;
        for (String header : IP_HEADER_CANDIDATES) {
            String ip = request.getHeader(header);
            ip = getFirstNotUnknownIp(ip);
            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
                remoteIp = ip;
            }
        }

        if (StringUtils.isBlank(remoteIp)) {
            remoteIp = request.getRemoteAddr();
        }

        return isIpV4(remoteIp) ? remoteIp : null;
    }

    private static String getFirstNotUnknownIp(String ip) {
        if (ip == null) {
            return null;
        }
        String[] ips = ip.split(",");
        for (String ip1 : ips) {
            ip1 = StringUtils.strip(ip1);
            if (!"unknown".equalsIgnoreCase(ip1)) {
                return ip1;
            }
        }
        return null;
    }

    public static String getLocalIp() {
        return getLocalIpV4();
    }

    public static String getLocalIpV4() {
        String ipAddress = null;
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                NetworkInterface intf = (NetworkInterface) en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = (InetAddress) enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                        ipAddress = inetAddress.getHostAddress().toString();
                    }
                }
            }
        } catch (SocketException ex) {
            throw new RuntimeException();
        }

        return ipAddress;
    }

    // 将127.0.0.1形式的IP地址转换成十进制整数，这里没有进行任何错误处理
    public static long ipv4ToLong(String strIp) {
        return Ipv4Util.ipv4ToLong(strIp);
    }

    // 将十进制整数形式转换成127.0.0.1形式的ip地址
    public static String longToIpv4(long longIp) {
        return Ipv4Util.longToIpv4(longIp);
    }
}
